package process.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

import process.model.DetailP;
import process.model.event.DetailEvent;
import process.service.DetailParserService;

/**
 * @author tvo35
 * 
 */

@Service
public class DetailParserServiceImpl implements DetailParserService {
	
	@Autowired
	private EventBus eventBus;
	
	@PostConstruct
	public void initialize() {
		eventBus.register(this);
	}
	
	public DetailP parse(Document doc, String productCode) throws IOException {
		Elements elements = doc.getElementsContainingOwnText(productCode);
		for (Element element : elements) {
			//System.out.println(element.html());
			Element parent = findRectWay1(element);
			if (parent == null) {
				parent = findRectWay2(element);
			}

			if (parent == null)
				return null;

			//System.out.println(parent.html());
			Elements anchors = parent.select("a[href]");
			Element name = findMaxElementByOwnText(anchors);
			Element image = parent.select("img").first();

			DetailP detail = new DetailP();
			detail.setName(name.ownText());
			detail.setImageUrl(image.absUrl("src"));
			detail.setDetailUrl(name.absUrl("href"));
			return detail;
			// System.out.println(name.ownText());
			// System.out.println(image.attr("src"));
			// System.out.println(name.absUrl("href"));

		}

		return null;
	}

	private Element findRectWay1(Element child) {
		Element parent = child.parent();
		if (parent == null)
			return parent;
		Elements siblings = parent.siblingElements();
		List<Boolean> posibilities = new ArrayList<Boolean>();
		for (Element element : siblings) {
			posibilities.add(compareElement(parent, element));
		}

		if (calRate(posibilities) > 1) {
			return parent;
		} else {
			return findRectWay1(parent);
		}
	}

	private Element findRectWay2(Element child) {
		Element parent = child.parent();
		if (parent == null)
			return parent;

		Elements anchors = parent.select("a[href]");
		if (anchors != null && !anchors.isEmpty()) {
			Element name = findMaxElementByOwnText(anchors);
			Element image = parent.select("img").first();
			if (name != null && image != null) {
				return parent;
			} else {
				return findRectWay2(parent);
			}
		} else {
			return findRectWay2(parent);
		}

	}

	private double calRate(List<Boolean> posibilities) {
		int iTrue = 0, iFalse = 0;
		for (Boolean b : posibilities) {
			if (b)
				iTrue++;
			else
				iFalse++;
		}

		if (iFalse == 0) {
			return iTrue;
		}

		else
			return iTrue / iFalse;
	}

	private boolean compareElement(Element element1, Element element2) {
		if (element1.tagName().equalsIgnoreCase(element2.tagName())) {
			if (!element1.className().equalsIgnoreCase("")) {
				if (element1.className().equalsIgnoreCase(element2.className()))
					return true;
			}
			if (element1.children().size() == element2.children().size()) {
				int size = element1.children().size();
				for (int j = 0; j < size; j++) {
					if (!element1
							.children()
							.get(j)
							.tagName()
							.equalsIgnoreCase(
									element2.children().get(j).tagName())) {
						return false;
					}
				}
				return true;
			}
		}
		return false;
	}

	private Element findMaxElementByOwnText(Elements elements) {
		Element max = elements.get(0);
		int count_max = max.ownText().length();
		Element element;
		for (int i = 1; i < elements.size(); i++) {
			element = elements.get(i);
			int count_node = element.ownText().length();
			if (count_node > count_max) {
				count_max = count_node;
				max = element;
			}
		}
		return max;
	}
	
	@Subscribe
	public void handleDetailEvent(DetailEvent event) {
		System.out.println(event.getProductCode());
	}
}
